## Vue.js

### 起步

#### Hello World

引入`Vue.js`文件

```
	<div id="app">
    	{{message}}
    </div>
    new Vue({
    	el:"#app"
        data:{
        	message:"Hello Vue.js!"
        }
    })
```

#### 双向绑定

`v-model`

```
	<div>
    	<p>{{message}}</p>
        <input v-model="message"/>
    </div>
    new Vue({
    	el:"#app",
        data:{
        	message:"Hello Vue.js"
        }
    })
```

#### 渲染列表： `v-for`

```
	<div>
    	<ul>
        	<li v-for="todo in todos">
            	{{todo.text}}
            </li>
        </ul>
    </div>
    
    new Vue({
    	el:"#app",
        data:{
        	todos:[
            {text:"aaaaaa"},
            {text:"bbbbbb"}
            ]
        }
    })
```

#### 处理用户输入 ： `v-on:click`

```
	<div>
    	<p>{{message}}</p>
        <button v-on:click="reverseMessage" >Reverse Message</button>
    </div>
    
    new Vue({
    	el:"#app",
        data:{
        	message:"Hello"
        },
        methods:{
        	reverseMessage:function(){
            	this.message = this.message.split('').revserse().join('')
            }
        }
    })
```

### 概述

`Vue.js`  是一个构建数据驱动的web界面的库。
目标：尽可能通过简单的API实现响应的数据绑定和组合的视图组件。

不是一个全能框架：聚焦于视图层。

#### 响应的数据绑定

DOM与数据同步，只要修改了数据， 响应的DOM会跟着改变。
使得代码更容易撰写、理解与维护。



### Vue 实例

#### 构造器

`ViewModel`

```
	var vm = new Vue({
        // 
    })
```

扩展 `Vue` 构造器

```
	var MyComponent = Vue.extent({
    	//
    })
    
    var myC = new MyCompontent()
```

#### 属性与方法

每个Vue实例都会**代理** `data` 对象里所有的属性
且都是响应的。

如果在创建对象之后 添加了新的属性，视图层不会更新。！！

属性和方法都有前缀`$`，以便与代理的数据属性区分。

```
	var data = {a:1}
    var vm = new Vue({
    	el:"#example",
        data:data
    })
    
    vm.$data === data // ->true
    vm.$el === document.getElementById("example") // -> true
    
    // $watch 是一个实例方法
    vm.$watch('a', function(newVal, oldVal){
    	// 这个回调将在 vm.a 改变后调用
    })
```

#### 实例的生命周期

- 数据观察
- 编译模板
- 创建必要的数据绑定

在运行过程中，调用一些生命周期钩子，给自定义逻辑提供机会。

egs：`created`

```
	var vm = new Vue({
    	data:{
        	a:1
        },
        created: function(){
            console.log("this a is: " + this.a)
        }
    })
    
    // -> this a is: 1
```

钩子： `compiled` `ready` `destroyed` 
狗子的 `this` 指向 Vue 实例。



### 数据绑定语法

#### 文本

数据绑定：

`<span>Mesage:{{msg}}</span>`

单次
`<span>Mesage:{{*msg}}</span>`

#### 原始的 HTML

`<div>{{{raw_html}}}</div>`

Note:在网站上动态渲染任意html非常危险，容易导致XSS攻击。永不用于用户提交的内容


#### javascript 表达式

限制：每个绑定只能包含单个表达式

`{{number+1}}`

`{{ok ? "YES" : "NO"}}`

#### 过滤器

管道符 `｜`

#### 指令

`<p v-if="greeting">Hello</p>`


#### 参数

`<a v-bind:href="url"></a>`

`<a href="{{url}}"></a>`

#### 修饰符

#### 缩写

##### v-bind

`v-bind:href` -> `:href`

##### v-on

`v-on:click` -> `@click`

### 计算属性

尽量不要在模版中使用过多的表达式 不利于维护

如果需要多于一个表达式，使用 **计算属性**

#### 基础例子

```
	<div id="example">
    	a={{a}},b={{b}}
    </div>
    
    var vm = new Vue({
    	el: "#example",
        daeta:{
        	a:1
        },
        computed:{
        	b:function(){
            	return this.a+1
            }
        }
    })
```
结果
` a=1,b=2`

#### 计算属性 vm.$watch

```
	var vm = new Vue({
    	data:{
        	firstName:'Foo',
            lastName: 'Bar'
        },
        computed: {
        	fullName: function(){
            	return this.firstName + " " + this.lastName
            }
        }
    })
```

#### setter

默认提供一个getter， 需要是提供一个setter

```
	//...
    computed:{
    	get:function(){
        	return this.firstName + ' ' + this.lastName
        }
        setter: function(newValue){
        	var names = newValue.split('')
            this.firstName = names[0]
            this.lastName = names[names.length - 1]
        }
    }
```

### class 与 style 绑定

`v-bind`

#### 对象语法

传给 `v-bind:class` 一个对象。以动态的切换class。
可以与 class 属性共存

`<div class="static" v-bind:class="{'class-a':isA, 'class-b': isB}"></div>`

```
	data:{
    	isA:true,
        isB:false
    }
```
->

`<div class="static class-a></div>`

当 isA 和 isB 改变时 class也改变


#### 数组语法

`<div v-bind:class="[classA, classB]">`

```
	data:{
    	classA: "class-a",
        classB: "class-b"
    }
```
->
`<div class="class-a class-b></div>`

也可以在赋值的时候 使用**三元表达式**

`<div v-bind:class="[classA, isB ? classB : '']"></div>`

#### 对象语法

```
	data:{
    	styleObject:{
        	color:'red',
            fontSize:'12px'
        }
    }
```

`<div v-bind:style="{color:activeColor, fontSize:fontSize+'px'}"></div>`
or
`<div v-bind:style="styleObject"></div>`
or
`<div v-bind:style="[styleObjectA, styleObjectB]"></div>`


#### 自动添加前缀

如`transform`， 会自动检测并添加相应的前缀！


### 条件渲染 

`v-if`
`v-show`:类似于 css 属性的 `display`
`v-else`

条件频繁切换使用 `v-show` 相反使用 `v-if`

### 列表渲染

`v-for`

```
	<ul>
    	<li v-for="item in items">
        	{{parentMessage}} - {{$index}} - {{item.message}}
        </li>
    </ul>
```

```
	var example1 = new Vue({
    	el: "#example-1",
        data:{
        	items:[
            	{message:"Foo"},
            	{message:"Bar"}
            ]
        }
    })
```

`$index`: 当前索引

`v-for="(index, item) in items"`

字典：`v-for="(key, value) in items"`



#### 变异方法

包装了被观察数组的变异方法。故他们能出发视图更新。

* push()
* pop()
* shift()
* unshift()
* splice()
* sort()
* reverse()

#### 替换数组

在使用非变异方法时，直接替换旧数组：非常高效的操作

```
	example1.items = example1.items.filter(function(item){
    	return item.message.match(/Foo/)
    })
```

#### track-by

保持不变的列表
不用渲染全部的列表

egs：
```
	{
    	items:[
        	{_uid:'232',...},
            {_uid:'112',...}
        ]
    }
    
    <div v-for="item in items" track-by="_uid">
     //content
    </div>
```
当items被替换时，遇到 _uid:'232' 的时候 便会复用该值


#### track-by $index

强制让 `v-for` 进入原位更新模式：片段不会被移动。而是简单地以对应索引的新值刷新。
这种模式也能处理数据数组中重复的值。

##### 问题

1.直接用索引设置元素： `vm.items[0] = {}`

	使用 `$set`

    `example1.items.$set(0, {childMsg: "Changed!"})`

2.修改数据的长度 `vm.ites.length=0`

	使用空数组替换


#### 对象 `v-for`

除了 `$index` 还可以访问另外一个特殊变量 `$key`

### 方法与事件处理器

#### 方法处理器

`v-on` 指定监听DOM事件

```
	<div id="example">
    	<button v-on:click="greet">Greet</button>
    </div>
```

绑定一个处理器方法。

```
	var vm = new Vue({
    	el:"#example",
        data:{
        	name:"Vue.js"
        },
        methods:{
        	greet:function(event){
            	alert("Hello"+this.name + "!")
                alert(event.target.tagName)
            }
        }
    })
```

#### 内联语句处理器

```
	<div id="example-2">
    	<button v-on:click="say('hi')">Say Hi</button>
        <button v-on:click="say('what)">Say What</button>
    </div>
    
    new Vue({
    	el: "#example-2",
        methods:{
        	say:function(msg){
            	alert(msg)
            }
        }
    })
```

也可以在内联语句处理器中访问原生的DOM事件。可以用特殊的变量 `$event`

`<button v-on:click="say('h', $event)">submit</button>`


#### 事件修饰符

`event.preventDefault()`  `event.stopPropagation()`.

为了解决这个问题。提供事件修饰符： `.prevent`  `.stop`

```
	// 防止单击事件冒泡
	<a v-on:click.stop="doThis"></a>
    
    // 提交事件不再重载页面
    <form v-on:submit.prevent="onSubmit"></form
    // 串联
    <a v-on:click.stop.prevent="doThis"></a>

	// 只有修饰符
    <form v-on:submit.prevent></form>
    
    // 添加事件兼听器时使用 capture 模式
    <div v-on:click.capture="doThis"></div>
    
    // 只当事件在该元素本身 而不是子元素触发时触发回调
    
    <div v-on:click.self="doThis"></div>
```

#### 按键修饰符

`v-on:keyup.13="submit"`

提供别名

`v-on:keyon.enter="submit"`

- enter
- tab
- delete
- esc
- space
- up
- down
- left
- right

支持单字母

自定义按键别名

`Vue.directive('on').keyCodes.f1 = 112`

#### 为什么在HTML中监听事件？

事件处理方法和表达式都严格绑定在当前视图的 ViewModel上
不会导致维护困难

好处

代码方法清晰
无需手动绑定事件
当一个ViewModel被销毁时，所有的事件处理器都会被自动删除。

### 表单控件绑定

#### 基础用法

`v-model` 在表单控件上创建双向数据绑定。

#### Text

```
	<span>Message is: {{message}}</span>
    <br>
    <input type="text" v-model="message" placeholder="edit me">
```

#### Checkbox

```
	<input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{checked}}</label>
```

多个狗选框，绑定到同一个数组

```
	<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
    <label for="jack">Jack</label>
    <input type="checkbox" id="john" value="John" v-model="checkedNames">
    <label for="john">John</label>
    <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
    <label for="mike">Mike</label>
    <br>
    <span>Checked names: {{ checkedNames | json }}</span>


	new Vue({
    	el:'input',
        data:{
        	checkedNames:[]
        }
    })
```

绑定数据

```
	<input
      type="checkbox"
      v-model="toggle"
      v-bind:true-value="a"
      v-bind:false-value="b">
      
      vm.toggle===vm.a
      vm.toggle===vm.b
```

#### Radio


```
	<input type="radio" id="one" value="One" v-model="picked">
    <label for="one">One</label>
    <br>
    <input type="radio" id="two" value="Two" v-model="picked">
    <label for="two">Two</label>
    <br>
    <span>Picked: {{ picked }}</span>
```

数据绑定：

```
	<input type="radio" v-model="pick" v-bind:vlaue="a">
    
    // 选中
    vm.pick===vm.a
```

#### Select

```
        <select v-model="selected">
        <option selected>A</option>
        <option>B</option>
        <option>C</option>
        </select>
        <span>Selected: {{ selected }}</span>

```

数据绑定

```
	<select v-model="selected">
    	<option v-bind:value="{number:123}">123</option>
    </select>
    
    typeof vm.selected
    vm.selected.number // -> 123
```

多选


动态选项  `v-for`



#### lazy

在默认情况下，`v-model` 在 `input` 事件中同步输入框值与数据，可以添加
一个特性 `lazy`， 从而改到在 `change` 事件中同步

```
	<input v-model="msg" lazy>
```

#### number

自动将用户输入保持为数字，可以添加一个特性 `number`

`<input v-model="age" number>`

#### debounce

设置一个最小的延时，在每次敲击之后延时同步输入框的值与数据。
用在每次更新都要进行高耗操作（ajax），较为有用


Note：`debounce` 参数不会延迟 input 事件：它延迟 写入 底层数据。
因此在使用 `debounce` 时应当 用 `vm.$watch()` 响应数据的变化

若想延迟DOM事件。使用 `debounce 过滤器`

### 过渡

使用 `vue.js` 过渡系统，可以在DOM中插入或者移除时自动应用过渡效果
在相应的 javascript 钩子函数中执行自定义的 DOM 操作

需要在目标元素中使用 `transition` 特性

`<div v-if="show" transition="my-transition"></div>`

transition 可以与

- v-if
- v-show
- v-for(只为插入和删除出发)
- 动态组件
- 在组件的根节点上，并且被 vue 实例 DOM 方法 出发（如 `vm.$appendTo(el)`）

当插入或者删除带有过度的元素时

1、尝试以 ID `my-transition` 查找 javascript 函数－－ 通过 `Vue.transition(id, hooks)` 或 `transitions` 选项注册.
2、自动嗅探目标元素是否有 css 过渡或动画，并在合适时添加／删除css类名
3、如果没有找到，将立即执行

#### CSS 过渡

`<div v-if="show" transition="fade">Hello</div>`

当 `this.show` 变化时，类 `.fade-transition` 会被添加到dom中，然后依次添加 `fade-enter` `fade-leave`

设置相应的css样式 产生过渡效果

如果没有相应的 transtion id值 会使用默认的 `v-transition` `v-enter` `v-leave`

##### 自定义过渡类名




#### javascript 过渡


















